<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Discrete Fourier Transform</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d9/df8/tutorial_root.html">OpenCV Tutorials</a></li><li class="navelem"><a class="el" href="../../de/d7a/tutorial_table_of_content_core.html">The Core Functionality (core module)</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Discrete Fourier Transform </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><b>Prev Tutorial:</b> <a class="el" href="../../d3/dc1/tutorial_basic_linear_transform.html">Changing the contrast and brightness of an image!</a></p>
<p><b>Next Tutorial:</b> <a class="el" href="../../dd/d74/tutorial_file_input_output_with_xml_yml.html">File Input and Output using XML and YAML files</a></p>
<table class="doxtable">
<tr>
<th align="right"></th><th align="left"></th></tr>
<tr>
<td align="right">Original author </td><td align="left">Bernát Gábor </td></tr>
<tr>
<td align="right">Compatibility </td><td align="left">OpenCV &gt;= 3.0 </td></tr>
</table>
<h2>Goal </h2>
<p>We'll seek answers for the following questions:</p>
<ul>
<li>What is a Fourier transform and why use it?</li>
<li>How to do it in OpenCV?</li>
<li>Usage of functions such as: <b><a class="el" href="../../d2/de8/group__core__array.html#ga2ac1049c2c3dd25c2b41bffe17658a36" title="Forms a border around an image. ">copyMakeBorder()</a></b> , <b><a class="el" href="../../d2/de8/group__core__array.html#ga7d7b4d6c6ee504b30a20b1680029c7b4" title="Creates one multi-channel array out of several single-channel ones. ">merge()</a></b> , <b><a class="el" href="../../d2/de8/group__core__array.html#gadd6cf9baf2b8b704a11b5f04aaf4f39d" title="Performs a forward or inverse Discrete Fourier transform of a 1D or 2D floating-point array...">dft()</a></b> , <b><a class="el" href="../../d2/de8/group__core__array.html#ga6577a2e59968936ae02eb2edde5de299" title="Returns the optimal DFT size for a given vector size. ">getOptimalDFTSize()</a></b> , <b><a class="el" href="../../d0/de1/group__core.html#ga4eba02a849f926ee1764acde47108753">log()</a></b> and <b><a class="el" href="../../dc/d84/group__core__basic.html#ga1b6a396a456c8b6c6e4afd8591560d80">normalize()</a></b> .</li>
</ul>
<h2>Source code </h2>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'><p> You can <a href="https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp">download this from here</a> or find it in the <code>samples/cpp/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.cpp</code> of the OpenCV source code library. </p> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'><p> You can <a href="https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/core/discrete_fourier_transform/DiscreteFourierTransform.java">download this from here</a> or find it in the <code>samples/java/tutorial_code/core/discrete_fourier_transform/DiscreteFourierTransform.java</code> of the OpenCV source code library. </p> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'><p> You can <a href="https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.py">download this from here</a> or find it in the <code>samples/python/tutorial_code/core/discrete_fourier_transform/discrete_fourier_transform.py</code> of the OpenCV source code library. </p> </div> <p>Here's a sample usage of <b><a class="el" href="../../d2/de8/group__core__array.html#gadd6cf9baf2b8b704a11b5f04aaf4f39d" title="Performs a forward or inverse Discrete Fourier transform of a 1D or 2D floating-point array...">dft()</a></b> :</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d0/d9c/core_2include_2opencv2_2core_8hpp.html">opencv2/core.hpp</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d1/d4f/imgproc_2include_2opencv2_2imgproc_8hpp.html">opencv2/imgproc.hpp</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d6/d87/imgcodecs_8hpp.html">opencv2/imgcodecs.hpp</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="../../d4/dd5/highgui_8hpp.html">opencv2/highgui.hpp</a>&quot;</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d8/dcc/namespacestd.html">std</a>;</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> help(<span class="keywordtype">char</span> ** argv)</div><div class="line">{</div><div class="line">    cout &lt;&lt; endl</div><div class="line">        &lt;&lt;  <span class="stringliteral">&quot;This program demonstrated the use of the discrete Fourier transform (DFT). &quot;</span> &lt;&lt; endl</div><div class="line">        &lt;&lt;  <span class="stringliteral">&quot;The dft of an image is taken and it&#39;s power spectrum is displayed.&quot;</span>  &lt;&lt; endl &lt;&lt; endl</div><div class="line">        &lt;&lt;  <span class="stringliteral">&quot;Usage:&quot;</span>                                                                      &lt;&lt; endl</div><div class="line">        &lt;&lt; argv[0] &lt;&lt; <span class="stringliteral">&quot; [image_name -- default lena.jpg]&quot;</span> &lt;&lt; endl &lt;&lt; endl;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> ** argv)</div><div class="line">{</div><div class="line">    help(argv);</div><div class="line"></div><div class="line">    <span class="keyword">const</span> <span class="keywordtype">char</span>* filename = argc &gt;=2 ? argv[1] : <span class="stringliteral">&quot;lena.jpg&quot;</span>;</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> I = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">imread</a>( <a class="code" href="../../d6/dba/group__core__utils__samples.html#ga3a33b00033b46c698ff6340d95569c13">samples::findFile</a>( filename ), <a class="code" href="../../d8/d6a/group__imgcodecs__flags.html#gga61d9b0126a3e57d9277ac48327799c80ae29981cfc153d3b0cef5c0daeedd2125">IMREAD_GRAYSCALE</a>);</div><div class="line">    <span class="keywordflow">if</span>( I.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abbec3525a852e77998aba034813fded4">empty</a>()){</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;Error opening image&quot;</span> &lt;&lt; endl;</div><div class="line">        <span class="keywordflow">return</span> EXIT_FAILURE;</div><div class="line">    }</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> padded;                            <span class="comment">//expand input image to optimal size</span></div><div class="line">    <span class="keywordtype">int</span> m = <a class="code" href="../../d2/de8/group__core__array.html#ga6577a2e59968936ae02eb2edde5de299">getOptimalDFTSize</a>( I.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abed816466c45234254d25bc59c31245e">rows</a> );</div><div class="line">    <span class="keywordtype">int</span> n = <a class="code" href="../../d2/de8/group__core__array.html#ga6577a2e59968936ae02eb2edde5de299">getOptimalDFTSize</a>( I.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa3e5a47585c9ef6a0842556739155e3e">cols</a> ); <span class="comment">// on the border add zero values</span></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga2ac1049c2c3dd25c2b41bffe17658a36">copyMakeBorder</a>(I, padded, 0, m - I.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abed816466c45234254d25bc59c31245e">rows</a>, 0, n - I.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa3e5a47585c9ef6a0842556739155e3e">cols</a>, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, <a class="code" href="../../d1/da0/classcv_1_1Scalar__.html#ac1509a4b8454fe7fe29db069e13a2e6f">Scalar::all</a>(0));</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> planes[] = {<a class="code" href="../../df/dfc/classcv_1_1Mat__.html">Mat_&lt;float&gt;</a>(padded), <a class="code" href="../../d3/d63/classcv_1_1Mat.html#a0b57b6a326c8876d944d188a46e0f556">Mat::zeros</a>(padded.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a146f8e8dda07d1365a575ab83d9828d1">size</a>(), <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>)};</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> complexI;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga7d7b4d6c6ee504b30a20b1680029c7b4">merge</a>(planes, 2, complexI);         <span class="comment">// Add to the expanded another plane with zeros</span></div><div class="line"><span class="comment"></span></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#gadd6cf9baf2b8b704a11b5f04aaf4f39d">dft</a>(complexI, complexI);            <span class="comment">// this way the result may fit in the source matrix</span></div><div class="line"><span class="comment"></span></div><div class="line">    <span class="comment">// compute the magnitude and switch to logarithmic scale</span></div><div class="line">    <span class="comment">// =&gt; log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))</span></div><div class="line"><span class="comment"></span>    <a class="code" href="../../d2/de8/group__core__array.html#ga0547c7fed86152d7e9d0096029c8518a">split</a>(complexI, planes);                   <span class="comment">// planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))</span></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga6d3b097586bca4409873d64a90fe64c3">magnitude</a>(planes[0], planes[1], planes[0]);<span class="comment">// planes[0] = magnitude</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> magI = planes[0];</div><div class="line"></div><div class="line">    magI += <a class="code" href="../../d1/da0/classcv_1_1Scalar__.html#ac1509a4b8454fe7fe29db069e13a2e6f">Scalar::all</a>(1);                    <span class="comment">// switch to logarithmic scale</span></div><div class="line">    <a class="code" href="../../d0/de1/group__core.html#ga4eba02a849f926ee1764acde47108753">log</a>(magI, magI);</div><div class="line"></div><div class="line">    <span class="comment">// crop the spectrum, if it has an odd number of rows or columns</span></div><div class="line">    magI = magI(<a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, 0, magI.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa3e5a47585c9ef6a0842556739155e3e">cols</a> &amp; -2, magI.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abed816466c45234254d25bc59c31245e">rows</a> &amp; -2));</div><div class="line"></div><div class="line">    <span class="comment">// rearrange the quadrants of Fourier image  so that the origin is at the image center</span></div><div class="line">    <span class="keywordtype">int</span> cx = magI.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa3e5a47585c9ef6a0842556739155e3e">cols</a>/2;</div><div class="line">    <span class="keywordtype">int</span> cy = magI.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#abed816466c45234254d25bc59c31245e">rows</a>/2;</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> q0(magI, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, 0, cx, cy));   <span class="comment">// Top-Left - Create a ROI per quadrant</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> q1(magI, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(cx, 0, cx, cy));  <span class="comment">// Top-Right</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> q2(magI, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, cy, cx, cy));  <span class="comment">// Bottom-Left</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> q3(magI, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(cx, cy, cx, cy)); <span class="comment">// Bottom-Right</span></div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> tmp;                           <span class="comment">// swap quadrants (Top-Left with Bottom-Right)</span></div><div class="line">    q0.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77">copyTo</a>(tmp);</div><div class="line">    q3.copyTo(q0);</div><div class="line">    tmp.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77">copyTo</a>(q3);</div><div class="line"></div><div class="line">    q1.copyTo(tmp);                    <span class="comment">// swap quadrant (Top-Right with Bottom-Left)</span></div><div class="line">    q2.copyTo(q1);</div><div class="line">    tmp.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a33fd5d125b4c302b0c9aa86980791a77">copyTo</a>(q2);</div><div class="line"></div><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga1b6a396a456c8b6c6e4afd8591560d80">normalize</a>(magI, magI, 0, 1, <a class="code" href="../../d2/de8/group__core__array.html#ggad12cefbcb5291cf958a85b4b67b6149fa9f0c1c342a18114d47b516a88e29822e">NORM_MINMAX</a>); <span class="comment">// Transform the matrix with float values into a</span></div><div class="line">                                            <span class="comment">// viewable image form (float between values 0 and 1).</span></div><div class="line"><span class="comment"></span></div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>(<span class="stringliteral">&quot;Input Image&quot;</span>       , I   );    <span class="comment">// Show the result</span></div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>(<span class="stringliteral">&quot;spectrum magnitude&quot;</span>, magI);</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">waitKey</a>();</div><div class="line"></div><div class="line">    <span class="keywordflow">return</span> EXIT_SUCCESS;</div><div class="line">}</div></div><!-- fragment -->  </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line"><span class="keyword">import</span> org.opencv.core.*;</div><div class="line"><span class="keyword">import</span> org.opencv.highgui.HighGui;</div><div class="line"><span class="keyword">import</span> org.opencv.imgcodecs.Imgcodecs;</div><div class="line"></div><div class="line"><span class="keyword">import</span> java.util.List;</div><div class="line"><span class="keyword">import</span> java.util.*;</div><div class="line"></div><div class="line"><span class="keyword">class </span>DiscreteFourierTransformRun{</div><div class="line">    <span class="keyword">private</span> <span class="keywordtype">void</span> help() {</div><div class="line">        System.out.println(<span class="stringliteral">&quot;&quot;</span> +</div><div class="line">                <span class="stringliteral">&quot;This program demonstrated the use of the discrete Fourier transform (DFT). \n&quot;</span> +</div><div class="line">                <span class="stringliteral">&quot;The dft of an image is taken and it&#39;s power spectrum is displayed.\n&quot;</span> +</div><div class="line">                <span class="stringliteral">&quot;Usage:\n&quot;</span> +</div><div class="line">                <span class="stringliteral">&quot;./DiscreteFourierTransform [image_name -- default ../data/lena.jpg]&quot;</span>);</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keyword">public</span> <span class="keywordtype">void</span> run(<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>[] args){</div><div class="line"></div><div class="line">        help();</div><div class="line"></div><div class="line">        <a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a> filename = ((args.length &gt; 0) ? args[0] : <span class="stringliteral">&quot;../data/lena.jpg&quot;</span>);</div><div class="line"></div><div class="line">        Mat I = Imgcodecs.imread(filename, Imgcodecs.IMREAD_GRAYSCALE);</div><div class="line">        <span class="keywordflow">if</span>( I.empty() ) {</div><div class="line">            System.out.println(<span class="stringliteral">&quot;Error opening image&quot;</span>);</div><div class="line">            System.exit(-1);</div><div class="line">        }</div><div class="line"></div><div class="line">        Mat padded = <span class="keyword">new</span> Mat();                     <span class="comment">//expand input image to optimal size</span></div><div class="line">        <span class="keywordtype">int</span> m = Core.getOptimalDFTSize( I.rows() );</div><div class="line">        <span class="keywordtype">int</span> n = Core.getOptimalDFTSize( I.cols() ); <span class="comment">// on the border add zero values</span></div><div class="line">        Core.copyMakeBorder(I, padded, 0, m - I.rows(), 0, n - I.cols(), Core.BORDER_CONSTANT, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>.<a class="code" href="../../d1/da0/classcv_1_1Scalar__.html#ac1509a4b8454fe7fe29db069e13a2e6f">all</a>(0));</div><div class="line"></div><div class="line">        List&lt;Mat&gt; planes = <span class="keyword">new</span> ArrayList&lt;Mat&gt;();</div><div class="line">        padded.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adf88c60c5b4980e05bb556080916978b">convertTo</a>(padded, CvType.CV_32F);</div><div class="line">        planes.add(padded);</div><div class="line">        planes.add(Mat.zeros(padded.size(), CvType.CV_32F));</div><div class="line">        Mat complexI = <span class="keyword">new</span> Mat();</div><div class="line">        Core.merge(planes, complexI);         <span class="comment">// Add to the expanded another plane with zeros</span></div><div class="line"><span class="comment"></span></div><div class="line">        Core.dft(complexI, complexI);         <span class="comment">// this way the result may fit in the source matrix</span></div><div class="line"><span class="comment"></span></div><div class="line">        <span class="comment">// compute the magnitude and switch to logarithmic scale</span></div><div class="line">        <span class="comment">// =&gt; log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))</span></div><div class="line"><span class="comment"></span>        Core.split(complexI, planes);                               <span class="comment">// planes.get(0) = Re(DFT(I)</span></div><div class="line">                                                                    <span class="comment">// planes.get(1) = Im(DFT(I))</span></div><div class="line">        Core.magnitude(planes.get(0), planes.get(1), planes.get(0));<span class="comment">// planes.get(0) = magnitude</span></div><div class="line">        Mat magI = planes.get(0);</div><div class="line"></div><div class="line">        Mat matOfOnes = Mat.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a69ae0402d116fc9c71908d8508dc2f09">ones</a>(magI.size(), magI.type());</div><div class="line">        Core.add(matOfOnes, magI, magI);         <span class="comment">// switch to logarithmic scale</span></div><div class="line">        Core.log(magI, magI);</div><div class="line"></div><div class="line">        <span class="comment">// crop the spectrum, if it has an odd number of rows or columns</span></div><div class="line">        magI = magI.submat(<span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, 0, magI.cols() &amp; -2, magI.rows() &amp; -2));</div><div class="line"></div><div class="line">        <span class="comment">// rearrange the quadrants of Fourier image  so that the origin is at the image center</span></div><div class="line">        <span class="keywordtype">int</span> cx = magI.cols()/2;</div><div class="line">        <span class="keywordtype">int</span> cy = magI.rows()/2;</div><div class="line"></div><div class="line">        Mat q0 = <span class="keyword">new</span> Mat(magI, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, 0, cx, cy));   <span class="comment">// Top-Left - Create a ROI per quadrant</span></div><div class="line">        Mat q1 = <span class="keyword">new</span> Mat(magI, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(cx, 0, cx, cy));  <span class="comment">// Top-Right</span></div><div class="line">        Mat q2 = <span class="keyword">new</span> Mat(magI, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, cy, cx, cy));  <span class="comment">// Bottom-Left</span></div><div class="line">        Mat q3 = <span class="keyword">new</span> Mat(magI, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(cx, cy, cx, cy)); <span class="comment">// Bottom-Right</span></div><div class="line"></div><div class="line">        Mat tmp = <span class="keyword">new</span> Mat();               <span class="comment">// swap quadrants (Top-Left with Bottom-Right)</span></div><div class="line">        q0.copyTo(tmp);</div><div class="line">        q3.copyTo(q0);</div><div class="line">        tmp.copyTo(q3);</div><div class="line"></div><div class="line">        q1.copyTo(tmp);                    <span class="comment">// swap quadrant (Top-Right with Bottom-Left)</span></div><div class="line">        q2.copyTo(q1);</div><div class="line">        tmp.copyTo(q2);</div><div class="line"></div><div class="line">        magI.convertTo(magI, CvType.CV_8UC1);</div><div class="line">        Core.normalize(magI, magI, 0, 255, Core.NORM_MINMAX, CvType.CV_8UC1); <span class="comment">// Transform the matrix with float values</span></div><div class="line">                                                                            <span class="comment">// into a viewable image form (float between</span></div><div class="line">                                                                            <span class="comment">// values 0 and 255).</span></div><div class="line"><span class="comment"></span></div><div class="line">        HighGui.imshow(<span class="stringliteral">&quot;Input Image&quot;</span>       , I   );    <span class="comment">// Show the result</span></div><div class="line">        HighGui.imshow(<span class="stringliteral">&quot;Spectrum Magnitude&quot;</span>, magI);</div><div class="line">        HighGui.waitKey();</div><div class="line"></div><div class="line">        System.exit(0);</div><div class="line">    }</div><div class="line">}</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">public</span> <span class="keyword">class </span>DiscreteFourierTransform {</div><div class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keywordtype">void</span> main(<a class="code" href="../../dc/d84/group__core__basic.html#ga1f6634802eeadfd7245bc75cf3e216c2">String</a>[] args) {</div><div class="line">        <span class="comment">// Load the native library.</span></div><div class="line">        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);</div><div class="line">        <span class="keyword">new</span> DiscreteFourierTransformRun().run(args);</div><div class="line">    }</div><div class="line">}</div></div><!-- fragment -->  </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line"><span class="keyword">from</span> __future__ <span class="keyword">import</span> print_function</div><div class="line"><span class="keyword">import</span> sys</div><div class="line"></div><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">def </span>print_help():</div><div class="line">    <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&#39;&#39;&#39;</span></div><div class="line"><span class="stringliteral">    This program demonstrated the use of the discrete Fourier transform (DFT).</span></div><div class="line"><span class="stringliteral">    The dft of an image is taken and it&#39;s power spectrum is displayed.</span></div><div class="line"><span class="stringliteral">    Usage:</span></div><div class="line"><span class="stringliteral">    discrete_fourier_transform.py [image_name -- default lena.jpg]&#39;&#39;&#39;</span>)</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">def </span>main(argv):</div><div class="line"></div><div class="line">    print_help()</div><div class="line"></div><div class="line">    filename = argv[0] <span class="keywordflow">if</span> len(argv) &gt; 0 <span class="keywordflow">else</span> <span class="stringliteral">&#39;lena.jpg&#39;</span></div><div class="line"></div><div class="line">    I = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<a class="code" href="../../d6/dba/group__core__utils__samples.html#ga3a33b00033b46c698ff6340d95569c13">cv.samples.findFile</a>(filename), cv.IMREAD_GRAYSCALE)</div><div class="line">    <span class="keywordflow">if</span> I <span class="keywordflow">is</span> <span class="keywordtype">None</span>:</div><div class="line">        <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&#39;Error opening image&#39;</span>)</div><div class="line">        <span class="keywordflow">return</span> -1</div><div class="line">    </div><div class="line">    rows, cols = I.shape</div><div class="line">    m = <a class="code" href="../../d2/de8/group__core__array.html#ga6577a2e59968936ae02eb2edde5de299">cv.getOptimalDFTSize</a>( rows )</div><div class="line">    n = <a class="code" href="../../d2/de8/group__core__array.html#ga6577a2e59968936ae02eb2edde5de299">cv.getOptimalDFTSize</a>( cols )</div><div class="line">    padded = <a class="code" href="../../d2/de8/group__core__array.html#ga2ac1049c2c3dd25c2b41bffe17658a36">cv.copyMakeBorder</a>(I, 0, m - rows, 0, n - cols, cv.BORDER_CONSTANT, value=[0, 0, 0])</div><div class="line">    </div><div class="line">    planes = [np.float32(padded), np.zeros(padded.shape, np.float32)]</div><div class="line">    complexI = <a class="code" href="../../d2/de8/group__core__array.html#ga61f2f2bde4a0a0154b2333ea504fab1d">cv.merge</a>(planes)         <span class="comment"># Add to the expanded another plane with zeros</span></div><div class="line">    </div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#gadd6cf9baf2b8b704a11b5f04aaf4f39d">cv.dft</a>(complexI, complexI)         <span class="comment"># this way the result may fit in the source matrix</span></div><div class="line">    </div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga8027f9deee1e42716be8039e5863fbd9">cv.split</a>(complexI, planes)                   <span class="comment"># planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))</span></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga6d3b097586bca4409873d64a90fe64c3">cv.magnitude</a>(planes[0], planes[1], planes[0])<span class="comment"># planes[0] = magnitude</span></div><div class="line">    magI = planes[0]</div><div class="line">    </div><div class="line">    matOfOnes = np.ones(magI.shape, dtype=magI.dtype)</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga10ac1bfb180e2cfda1701d06c24fdbd6">cv.add</a>(matOfOnes, magI, magI) <span class="comment">#  switch to logarithmic scale</span></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga937ecdce4679a77168730830a955bea7">cv.log</a>(magI, magI)</div><div class="line">    </div><div class="line">    magI_rows, magI_cols = magI.shape</div><div class="line">    <span class="comment"># crop the spectrum, if it has an odd number of rows or columns</span></div><div class="line">    magI = magI[0:(magI_rows &amp; -2), 0:(magI_cols &amp; -2)]</div><div class="line">    cx = int(magI_rows/2)</div><div class="line">    cy = int(magI_cols/2)</div><div class="line"></div><div class="line">    q0 = magI[0:cx, 0:cy]         <span class="comment"># Top-Left - Create a ROI per quadrant</span></div><div class="line">    q1 = magI[cx:cx+cx, 0:cy]     <span class="comment"># Top-Right</span></div><div class="line">    q2 = magI[0:cx, cy:cy+cy]     <span class="comment"># Bottom-Left</span></div><div class="line">    q3 = magI[cx:cx+cx, cy:cy+cy] <span class="comment"># Bottom-Right</span></div><div class="line"></div><div class="line">    tmp = np.copy(q0)               <span class="comment"># swap quadrants (Top-Left with Bottom-Right)</span></div><div class="line">    magI[0:cx, 0:cy] = q3</div><div class="line">    magI[cx:cx + cx, cy:cy + cy] = tmp</div><div class="line"></div><div class="line">    tmp = np.copy(q1)               <span class="comment"># swap quadrant (Top-Right with Bottom-Left)</span></div><div class="line">    magI[cx:cx + cx, 0:cy] = q2</div><div class="line">    magI[0:cx, cy:cy + cy] = tmp</div><div class="line">    </div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga7bcf47a1df78cf575162e0aed44960cb">cv.normalize</a>(magI, magI, 0, 1, cv.NORM_MINMAX) <span class="comment"># Transform the matrix with float values into a</span></div><div class="line">    </div><div class="line">    <a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(<span class="stringliteral">&quot;Input Image&quot;</span>       , I   )    <span class="comment"># Show the result</span></div><div class="line">    <a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(<span class="stringliteral">&quot;spectrum magnitude&quot;</span>, magI)</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">cv.waitKey</a>()</div><div class="line"></div><div class="line"><span class="keywordflow">if</span> __name__ == <span class="stringliteral">&quot;__main__&quot;</span>:</div><div class="line">    main(sys.argv[1:])</div></div><!-- fragment -->  </div> <h2>Explanation </h2>
<p>The Fourier Transform will decompose an image into its sinus and cosines components. In other words, it will transform an image from its spatial domain to its frequency domain. The idea is that any function may be approximated exactly with the sum of infinite sinus and cosines functions. The Fourier Transform is a way how to do this. Mathematically a two dimensional images Fourier transform is:</p>
<p class="formulaDsp">
\[F(k,l) = \displaystyle\sum\limits_{i=0}^{N-1}\sum\limits_{j=0}^{N-1} f(i,j)e^{-i2\pi(\frac{ki}{N}+\frac{lj}{N})}\]
</p>
 <p class="formulaDsp">
\[e^{ix} = \cos{x} + i\sin {x}\]
</p>
<p>Here f is the image value in its spatial domain and F in its frequency domain. The result of the transformation is complex numbers. Displaying this is possible either via a <em>real</em> image and a <em>complex</em> image or via a <em>magnitude</em> and a <em>phase</em> image. However, throughout the image processing algorithms only the <em>magnitude</em> image is interesting as this contains all the information we need about the images geometric structure. Nevertheless, if you intend to make some modifications of the image in these forms and then you need to retransform it you'll need to preserve both of these.</p>
<p>In this sample I'll show how to calculate and show the <em>magnitude</em> image of a Fourier Transform. In case of digital images are discrete. This means they may take up a value from a given domain value. For example in a basic gray scale image values usually are between zero and 255. Therefore the Fourier Transform too needs to be of a discrete type resulting in a Discrete Fourier Transform (<em>DFT</em>). You'll want to use this whenever you need to determine the structure of an image from a geometrical point of view. Here are the steps to follow (in case of a gray scale input image <em>I</em>):</p>
<h4>Expand the image to an optimal size</h4>
<p>The performance of a DFT is dependent of the image size. It tends to be the fastest for image sizes that are multiple of the numbers two, three and five. Therefore, to achieve maximal performance it is generally a good idea to pad border values to the image to get a size with such traits. The <b><a class="el" href="../../d2/de8/group__core__array.html#ga6577a2e59968936ae02eb2edde5de299" title="Returns the optimal DFT size for a given vector size. ">getOptimalDFTSize()</a></b> returns this optimal size and we can use the <b><a class="el" href="../../d2/de8/group__core__array.html#ga2ac1049c2c3dd25c2b41bffe17658a36" title="Forms a border around an image. ">copyMakeBorder()</a></b> function to expand the borders of an image (the appended pixels are initialized with zero):</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    Mat padded;                            <span class="comment">//expand input image to optimal size</span></div><div class="line">    <span class="keywordtype">int</span> m = <a class="code" href="../../d2/de8/group__core__array.html#ga6577a2e59968936ae02eb2edde5de299">getOptimalDFTSize</a>( I.rows );</div><div class="line">    <span class="keywordtype">int</span> n = <a class="code" href="../../d2/de8/group__core__array.html#ga6577a2e59968936ae02eb2edde5de299">getOptimalDFTSize</a>( I.cols ); <span class="comment">// on the border add zero values</span></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga2ac1049c2c3dd25c2b41bffe17658a36">copyMakeBorder</a>(I, padded, 0, m - I.rows, 0, n - I.cols, <a class="code" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838">BORDER_CONSTANT</a>, Scalar::all(0));</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        Mat padded = <span class="keyword">new</span> Mat();                     <span class="comment">//expand input image to optimal size</span></div><div class="line">        <span class="keywordtype">int</span> m = Core.getOptimalDFTSize( I.rows() );</div><div class="line">        <span class="keywordtype">int</span> n = Core.getOptimalDFTSize( I.cols() ); <span class="comment">// on the border add zero values</span></div><div class="line">        Core.copyMakeBorder(I, padded, 0, m - I.rows(), 0, n - I.cols(), Core.BORDER_CONSTANT, <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a>.<a class="code" href="../../d1/da0/classcv_1_1Scalar__.html#ac1509a4b8454fe7fe29db069e13a2e6f">all</a>(0));</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    rows, cols = I.shape</div><div class="line">    m = <a class="code" href="../../d2/de8/group__core__array.html#ga6577a2e59968936ae02eb2edde5de299">cv.getOptimalDFTSize</a>( rows )</div><div class="line">    n = <a class="code" href="../../d2/de8/group__core__array.html#ga6577a2e59968936ae02eb2edde5de299">cv.getOptimalDFTSize</a>( cols )</div><div class="line">    padded = <a class="code" href="../../d2/de8/group__core__array.html#ga2ac1049c2c3dd25c2b41bffe17658a36">cv.copyMakeBorder</a>(I, 0, m - rows, 0, n - cols, cv.BORDER_CONSTANT, value=[0, 0, 0])</div></div><!-- fragment --> </div> <h4>Make place for both the complex and the real values</h4>
<p>The result of a Fourier Transform is complex. This implies that for each image value the result is two image values (one per component). Moreover, the frequency domains range is much larger than its spatial counterpart. Therefore, we store these usually at least in a <em>float</em> format. Therefore we'll convert our input image to this type and expand it with another channel to hold the complex values:</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    Mat planes[] = {Mat_&lt;float&gt;(padded), Mat::zeros(padded.size(), <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>)};</div><div class="line">    Mat complexI;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga7d7b4d6c6ee504b30a20b1680029c7b4">merge</a>(planes, 2, complexI);         <span class="comment">// Add to the expanded another plane with zeros</span></div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        List&lt;Mat&gt; planes = <span class="keyword">new</span> ArrayList&lt;Mat&gt;();</div><div class="line">        padded.convertTo(padded, CvType.CV_32F);</div><div class="line">        planes.add(padded);</div><div class="line">        planes.add(Mat.zeros(padded.size(), CvType.CV_32F));</div><div class="line">        Mat complexI = <span class="keyword">new</span> Mat();</div><div class="line">        Core.merge(planes, complexI);         <span class="comment">// Add to the expanded another plane with zeros</span></div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    planes = [np.float32(padded), np.zeros(padded.shape, np.float32)]</div><div class="line">    complexI = <a class="code" href="../../d2/de8/group__core__array.html#ga61f2f2bde4a0a0154b2333ea504fab1d">cv.merge</a>(planes)         <span class="comment"># Add to the expanded another plane with zeros</span></div></div><!-- fragment --> </div> <h4>Make the Discrete Fourier Transform</h4>
<p>It's possible an in-place calculation (same input as output):</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#gadd6cf9baf2b8b704a11b5f04aaf4f39d">dft</a>(complexI, complexI);            <span class="comment">// this way the result may fit in the source matrix</span></div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        Core.dft(complexI, complexI);         <span class="comment">// this way the result may fit in the source matrix</span></div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#gadd6cf9baf2b8b704a11b5f04aaf4f39d">cv.dft</a>(complexI, complexI)         <span class="comment"># this way the result may fit in the source matrix</span></div></div><!-- fragment --> </div> <h4>Transform the real and complex values to magnitude</h4>
<p>A complex number has a real (<em>Re</em>) and a complex (imaginary - <em>Im</em>) part. The results of a DFT are complex numbers. The magnitude of a DFT is:</p>
<p class="formulaDsp">
\[M = \sqrt[2]{ {Re(DFT(I))}^2 + {Im(DFT(I))}^2}\]
</p>
<p>Translated to OpenCV code:</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga0547c7fed86152d7e9d0096029c8518a">split</a>(complexI, planes);                   <span class="comment">// planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))</span></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga6d3b097586bca4409873d64a90fe64c3">magnitude</a>(planes[0], planes[1], planes[0]);<span class="comment">// planes[0] = magnitude</span></div><div class="line">    Mat magI = planes[0];</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        Core.split(complexI, planes);                               <span class="comment">// planes.get(0) = Re(DFT(I)</span></div><div class="line">                                                                    <span class="comment">// planes.get(1) = Im(DFT(I))</span></div><div class="line">        Core.magnitude(planes.get(0), planes.get(1), planes.get(0));<span class="comment">// planes.get(0) = magnitude</span></div><div class="line">        Mat magI = planes.get(0);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga8027f9deee1e42716be8039e5863fbd9">cv.split</a>(complexI, planes)                   <span class="comment"># planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))</span></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga6d3b097586bca4409873d64a90fe64c3">cv.magnitude</a>(planes[0], planes[1], planes[0])<span class="comment"># planes[0] = magnitude</span></div><div class="line">    magI = planes[0]</div></div><!-- fragment --> </div> <h4>Switch to a logarithmic scale</h4>
<p>It turns out that the dynamic range of the Fourier coefficients is too large to be displayed on the screen. We have some small and some high changing values that we can't observe like this. Therefore the high values will all turn out as white points, while the small ones as black. To use the gray scale values to for visualization we can transform our linear scale to a logarithmic one:</p>
<p class="formulaDsp">
\[M_1 = \log{(1 + M)}\]
</p>
<p>Translated to OpenCV code:</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    magI += Scalar::all(1);                    <span class="comment">// switch to logarithmic scale</span></div><div class="line">    <a class="code" href="../../d0/de1/group__core.html#ga4eba02a849f926ee1764acde47108753">log</a>(magI, magI);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        Mat matOfOnes = Mat.ones(magI.size(), magI.type());</div><div class="line">        Core.add(matOfOnes, magI, magI);         <span class="comment">// switch to logarithmic scale</span></div><div class="line">        Core.log(magI, magI);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    matOfOnes = np.ones(magI.shape, dtype=magI.dtype)</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga10ac1bfb180e2cfda1701d06c24fdbd6">cv.add</a>(matOfOnes, magI, magI) <span class="comment">#  switch to logarithmic scale</span></div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga937ecdce4679a77168730830a955bea7">cv.log</a>(magI, magI)</div></div><!-- fragment --> </div> <h4>Crop and rearrange</h4>
<p>Remember, that at the first step, we expanded the image? Well, it's time to throw away the newly introduced values. For visualization purposes we may also rearrange the quadrants of the result, so that the origin (zero, zero) corresponds with the image center.</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    <span class="comment">// crop the spectrum, if it has an odd number of rows or columns</span></div><div class="line">    magI = magI(<a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, 0, magI.cols &amp; -2, magI.rows &amp; -2));</div><div class="line"></div><div class="line">    <span class="comment">// rearrange the quadrants of Fourier image  so that the origin is at the image center</span></div><div class="line">    <span class="keywordtype">int</span> cx = magI.cols/2;</div><div class="line">    <span class="keywordtype">int</span> cy = magI.rows/2;</div><div class="line"></div><div class="line">    Mat q0(magI, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, 0, cx, cy));   <span class="comment">// Top-Left - Create a ROI per quadrant</span></div><div class="line">    Mat q1(magI, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(cx, 0, cx, cy));  <span class="comment">// Top-Right</span></div><div class="line">    Mat q2(magI, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, cy, cx, cy));  <span class="comment">// Bottom-Left</span></div><div class="line">    Mat q3(magI, <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(cx, cy, cx, cy)); <span class="comment">// Bottom-Right</span></div><div class="line"></div><div class="line">    Mat tmp;                           <span class="comment">// swap quadrants (Top-Left with Bottom-Right)</span></div><div class="line">    q0.copyTo(tmp);</div><div class="line">    q3.copyTo(q0);</div><div class="line">    tmp.copyTo(q3);</div><div class="line"></div><div class="line">    q1.copyTo(tmp);                    <span class="comment">// swap quadrant (Top-Right with Bottom-Left)</span></div><div class="line">    q2.copyTo(q1);</div><div class="line">    tmp.copyTo(q2);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        <span class="comment">// crop the spectrum, if it has an odd number of rows or columns</span></div><div class="line">        magI = magI.submat(<span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, 0, magI.cols() &amp; -2, magI.rows() &amp; -2));</div><div class="line"></div><div class="line">        <span class="comment">// rearrange the quadrants of Fourier image  so that the origin is at the image center</span></div><div class="line">        <span class="keywordtype">int</span> cx = magI.cols()/2;</div><div class="line">        <span class="keywordtype">int</span> cy = magI.rows()/2;</div><div class="line"></div><div class="line">        Mat q0 = <span class="keyword">new</span> Mat(magI, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, 0, cx, cy));   <span class="comment">// Top-Left - Create a ROI per quadrant</span></div><div class="line">        Mat q1 = <span class="keyword">new</span> Mat(magI, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(cx, 0, cx, cy));  <span class="comment">// Top-Right</span></div><div class="line">        Mat q2 = <span class="keyword">new</span> Mat(magI, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(0, cy, cx, cy));  <span class="comment">// Bottom-Left</span></div><div class="line">        Mat q3 = <span class="keyword">new</span> Mat(magI, <span class="keyword">new</span> <a class="code" href="../../dc/d84/group__core__basic.html#ga11d95de507098e90bad732b9345402e8">Rect</a>(cx, cy, cx, cy)); <span class="comment">// Bottom-Right</span></div><div class="line"></div><div class="line">        Mat tmp = <span class="keyword">new</span> Mat();               <span class="comment">// swap quadrants (Top-Left with Bottom-Right)</span></div><div class="line">        q0.copyTo(tmp);</div><div class="line">        q3.copyTo(q0);</div><div class="line">        tmp.copyTo(q3);</div><div class="line"></div><div class="line">        q1.copyTo(tmp);                    <span class="comment">// swap quadrant (Top-Right with Bottom-Left)</span></div><div class="line">        q2.copyTo(q1);</div><div class="line">        tmp.copyTo(q2);</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    magI_rows, magI_cols = magI.shape</div><div class="line">    <span class="comment"># crop the spectrum, if it has an odd number of rows or columns</span></div><div class="line">    magI = magI[0:(magI_rows &amp; -2), 0:(magI_cols &amp; -2)]</div><div class="line">    cx = int(magI_rows/2)</div><div class="line">    cy = int(magI_cols/2)</div><div class="line"></div><div class="line">    q0 = magI[0:cx, 0:cy]         <span class="comment"># Top-Left - Create a ROI per quadrant</span></div><div class="line">    q1 = magI[cx:cx+cx, 0:cy]     <span class="comment"># Top-Right</span></div><div class="line">    q2 = magI[0:cx, cy:cy+cy]     <span class="comment"># Bottom-Left</span></div><div class="line">    q3 = magI[cx:cx+cx, cy:cy+cy] <span class="comment"># Bottom-Right</span></div><div class="line"></div><div class="line">    tmp = np.copy(q0)               <span class="comment"># swap quadrants (Top-Left with Bottom-Right)</span></div><div class="line">    magI[0:cx, 0:cy] = q3</div><div class="line">    magI[cx:cx + cx, cy:cy + cy] = tmp</div><div class="line"></div><div class="line">    tmp = np.copy(q1)               <span class="comment"># swap quadrant (Top-Right with Bottom-Left)</span></div><div class="line">    magI[cx:cx + cx, 0:cy] = q2</div><div class="line">    magI[0:cx, cy:cy + cy] = tmp</div></div><!-- fragment --> </div> <h4>Normalize</h4>
<p>This is done again for visualization purposes. We now have the magnitudes, however this are still out of our image display range of zero to one. We normalize our values to this range using the <a class="el" href="../../dc/d84/group__core__basic.html#ga1b6a396a456c8b6c6e4afd8591560d80">cv::normalize()</a> function.</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga1b6a396a456c8b6c6e4afd8591560d80">normalize</a>(magI, magI, 0, 1, <a class="code" href="../../d2/de8/group__core__array.html#ggad12cefbcb5291cf958a85b4b67b6149fa9f0c1c342a18114d47b516a88e29822e">NORM_MINMAX</a>); <span class="comment">// Transform the matrix with float values into a</span></div><div class="line">                                            <span class="comment">// viewable image form (float between values 0 and 1).</span></div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='java' style='display: none;'>Java</div><div class='toggleable_div label_java' style='display: none;'> <div class="fragment"><div class="line">        Core.normalize(magI, magI, 0, 255, Core.NORM_MINMAX, CvType.CV_8UC1); <span class="comment">// Transform the matrix with float values</span></div><div class="line">                                                                            <span class="comment">// into a viewable image form (float between</span></div><div class="line">                                                                            <span class="comment">// values 0 and 255).</span></div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga7bcf47a1df78cf575162e0aed44960cb">cv.normalize</a>(magI, magI, 0, 1, cv.NORM_MINMAX) <span class="comment"># Transform the matrix with float values into a</span></div><div class="line">    </div></div><!-- fragment --> </div> <h2>Result </h2>
<p>An application idea would be to determine the geometrical orientation present in the image. For example, let us find out if a text is horizontal or not? Looking at some text you'll notice that the text lines sort of form also horizontal lines and the letters form sort of vertical lines. These two main components of a text snippet may be also seen in case of the Fourier transform. Let us use <a href="https://raw.githubusercontent.com/opencv/opencv/master/samples/data/imageTextN.png">this horizontal</a> and <a href="https://raw.githubusercontent.com/opencv/opencv/master/samples/data/imageTextR.png">this rotated</a> image about a text.</p>
<p>In case of the horizontal text:</p>
<div class="image">
<img src="../../result_normal.jpg" alt="result_normal.jpg"/>
</div>
<p>In case of a rotated text:</p>
<div class="image">
<img src="../../result_rotated.jpg" alt="result_rotated.jpg"/>
</div>
<p>You can see that the most influential components of the frequency domain (brightest dots on the magnitude image) follow the geometric rotation of objects on the image. From this we may calculate the offset and perform an image rotation to correct eventual miss alignments. </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:34 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
